<meta charset="UTF-8" />
<title>Proxy debounce refresh</title>

<div id="result"></div>

<script>
    /**
     * @param { Function } fn
     * @param { number } delay
    */
    const debounce = function (fn, delay) {
        let timer = null;
        return function (...args) {
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(() => {
                fn(...args);
            }, delay);
        };
    };

    /**
     * @template T
     * @param { T } state
     * @param { (state:T) => void } fn
     * @returns { T }
    */
    const Proxy_debounce = function (state, fn) {
        const debounce_fn = debounce(fn);
        debounce_fn(state);
        return new Proxy(state, {
            get(target, key) {
                debounce_fn(state);
                console.log("get state key：" + key);
                return target[key];
            },
            set(target, key, value) {
                target[key] = value;
                debounce_fn(state);
                console.log("set state key：" + key);
            },
        });
    };

    /** @type { HTMLDivElement } */
    const result = document.getElementById("result");

    const module = Proxy_debounce({
        value: {
            a: {
                b: {
                    c: {
                        value: [1, 2, 3]
                    }
                }
            }
        },
    }, (state) => {
        result.innerHTML = `[${state.value.a.b.c.value.join(",")}]`;
    });

    module.value.a.b.c.value[1] = 900; // refresh

    setTimeout(() => {
        console.log("setTimeout 1000");
        module.value.a.b.c.value.splice(1, 1); // refresh
    }, 1000);

    const value = module.value.a.b.c.value; // refresh

    setTimeout(() => {
        console.log("setTimeout 2000");
        value.push(100);
    }, 2000);

    setTimeout(() => {
        console.log("setTimeout 3000");
        module.value; // refresh
    }, 3000);
</script>